package com.softeem.sanguo;

import javax.swing.*;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 玩家类：游戏中的主控角色
 * 子类继承抽象类之后，必须对抽象类中的抽象方法实现
 */
public class Hero extends Sprite {

    /**
     * 移动速度
     */
    private int speed = 15;
    /**
     * 初始玩家移动方向  R-右  L-左
     */
    private char dir = 'R';

    /**
     * 定时器：类似开关（执行定时任务）
     */
    private Timer timer;

    /**
     * 声明集合存储所有发射的篮球
     */
    CopyOnWriteArrayList<Ball> balls = new CopyOnWriteArrayList<>();

    //玩家血量
    int hp = 500;
    //玩家魔法值
    int mp = 500;

    /**
     * 定时任务
     */
    private class DanceTask extends TimerTask {
        //初始图片索引
        private int index;

        @Override
        public void run() {
            if (dir == 'R') {
                //始终让图片在0~lenth-1范围变化
                setImg(Images.ikun_right[++index % Images.ikun_right.length]);
            } else {
                setImg(Images.ikun_left[++index % Images.ikun_left.length]);
            }
        }
    }

    /**
     * 构造器：在创建对象时执行初始化操作
     *
     * @param panel 游戏元素绘制的主面板
     */
    public Hero(GamePanel panel) {
        super(panel);
    }

    @Override
    public void init() {
        //设置玩家的初始图片
        setImg(Images.ikun_right[0]);
        //设置玩家在界面中占据大小（即图片大小）
        setW(getImg().getWidth());
        setH(getImg().getHeight());
        //初始化玩家坐标
        setY(Config.SC_HEIGHT / 2 - getH() / 2);

        //创建定时器对象
        timer = new Timer();
        //创建定时任务对象
        DanceTask task = new DanceTask();
        //调度定时任务(延迟0毫秒开始每隔0.1秒执行一次)  1s=1000ms
        timer.schedule(task, 0, 100);
    }

    /**
     * 根据不同的按键码执行相关操作：
     * 移动
     * 攻击
     * 技能
     *
     * @param code 用于实现玩家行为控制的按键码
     */
    public void control(int code) {
        switch (code) {
            case 37:
                //左
                dir = 'L';
                setX(getX() - speed);
                //左移出界时从右侧出现
                if (getX() < -getW()) {
                    //如果地图为第一章，则不进行地图切换，并固定玩家位置
                    if (getPanel().mapIndex == 0) {
                        setX(0);
                    } else {
                        setX(Config.SC_WIDTH);
                        //切换上一张地图
                        getPanel().prevMap();
                    }
                }
                break;
            case 38:
                //上
                setY(getY() - speed);
                //防止上移出界
                if (getY() < (Config.SC_HEIGHT / 2 - getH() / 2)) {
                    setY(Config.SC_HEIGHT / 2 - getH() / 2);
                }
                break;
            case 39:
                //右
                dir = 'R';
                setX(getX() + speed);
                //右移出界时从屏幕左侧出现
                if (getX() > Config.SC_WIDTH) {
                    //判断当前是否是最后一张地图，若为最后一张，则不执行地图切换与位置变化
                    if (getPanel().mapIndex != Images.maps.length - 1) {
                        setX(-getW());
                        //切换下一张地图
                        getPanel().nextMap();
                    } else {
                        //固定玩家位置不变
                        setX(Config.SC_WIDTH - getW());
                    }
                }
                break;
            case 40:
                //下
                setY(getY() + speed);
                //防止下移出界
                if (getY() > Config.SC_HEIGHT - getH() * 3 / 2) {
                    setY(Config.SC_HEIGHT - getH() * 3 / 2);
                }
                break;
            case 32:
                //播放音效
                Utils.playMusic("shoot.mp3", false);
                //发射篮球
                Ball ball = new Ball(getPanel(), getX(), getY(), dir);
                //启动篮球的飞行线程
                new Thread(ball).start();
                //将创建的篮球存储到集合中
                balls.add(ball);
                break;
            case 82:
                //技能释放
                Utils.playMusic("skill.mp3", false);
                skill();
                break;
        }

        //遍历所有产生道具是否和玩家碰撞
        getPanel().foods.forEach(f -> {
            //检测碰撞
            if (!f.isDeath() && Utils.isHit(getX(), getY(), getW(), getH(), f.getX(), f.getY(), f.getW(), f.getH())) {
                //标记道具销毁
                f.destroy();
                //为玩家增加能量
                if (f.type == 0) {
                    //加血
                    hp += f.power;
                    //防止血量超出最大值
                    hp = Math.min(500, hp);
                } else {
                    //加蓝
                    mp += f.power;
                    mp = Math.min(500, mp);
                }
            }
        });

    }

    private void skill() {
        if(mp < 100){
            //如果魔法值不足，则技能无法释放
            return;
        }
        //随机减少魔法值
        mp -= 100;
        //左
        SkillBall b0 = new SkillBall(getPanel(), getX() - 20, getY(), '0');
        //上
        SkillBall b1 = new SkillBall(getPanel(), getX(), getY() - 20, '1');
        //右
        SkillBall b2 = new SkillBall(getPanel(), getX() + 20, getY(), '2');
        //下
        SkillBall b3 = new SkillBall(getPanel(), getX(), getY() + 20, '3');
        //左上
        SkillBall b4 = new SkillBall(getPanel(), getX() - 20, getY() - 20, '4');
        //右上
        SkillBall b5 = new SkillBall(getPanel(), getX() + 20, getY() - 20, '5');
        //右下
        SkillBall b6 = new SkillBall(getPanel(), getX() + 20, getY() + 20, '6');
        //左下
        SkillBall b7 = new SkillBall(getPanel(), getX() - 20, getY() + 20, '7');
        //启动所有球的飞行线程
        new Thread(b0).start();
        new Thread(b1).start();
        new Thread(b2).start();
        new Thread(b3).start();
        new Thread(b4).start();
        new Thread(b5).start();
        new Thread(b6).start();
        new Thread(b7).start();
        //将所有球加入集合
        balls.add(b0);
        balls.add(b1);
        balls.add(b2);
        balls.add(b3);
        balls.add(b4);
        balls.add(b5);
        balls.add(b6);
        balls.add(b7);
    }

    /**
     * 重写绘制方法，绘制玩家的血条和能量条
     *
     * @param g 画笔对象
     */
    @Override
    public void draw(Graphics g) {
        super.draw(g);

        //绘制玩家头像
        g.drawImage(Images.headIcon, 10, 10, 80, 80, null);

        //设置画笔颜色
        g.setColor(Color.RED);
        //绘制血条
        g.drawRect(100, 10, 380, 50);
        g.fillRect(100, 10, (int) (hp / 500.0 * 380), 50);

        g.setColor(Color.BLUE);
        //绘制怒气值
        g.drawRect(100, 70, 380, 20);
        g.fillRect(100, 70, (int) (mp / 500.0 * 380), 20);
    }

    @Override
    public void destroy() {
        //取消玩家定时任务
        timer.cancel();
        //播放死亡音效
        Utils.playMusic("die.mp3", false);
        //清理所有篮球
        balls.clear();
        //清理所有敌人
        getPanel().enemies.clear();
        //标记游戏结束
        getPanel().playing = false;
        //弹出结束对话框
        int i = JOptionPane.showConfirmDialog(getPanel(), "玩家死亡，是否重新开始?", "游戏结束", JOptionPane.YES_NO_OPTION);
        if (i == 0) {
            //关闭之前窗口
            getPanel().gameWindow.setVisible(false);
            //重新创建新窗口
            GameWindow gw = new GameWindow();
            gw.start();
        } else {
            //系统退出
            System.exit(0);
        }
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}
